package jannex.sql.extensions;

import jannex.Builder;
import jannex.Jannex;
import jannex.mapping.ResultSetHandler;
import jannex.internal.ExceptionFactory;
import jannex.sql.TypedResultSet;
import jannex.sql.Fetcher;

import java.sql.SQLException;
import java.util.Iterator;
import java.util.NoSuchElementException;

public class TypedResultSetImpl<E> extends ResultSetImpl implements TypedResultSet<E> {

    private ResultSetHandler<E> handler;

    public TypedResultSetImpl(java.sql.ResultSet resultSet, Jannex jannex, ResultSetHandler<E> handler) {
        super(resultSet, jannex);
        this.handler = handler;
    }

    @Override
    public E getObject() {
        return handler.handle(this);
    }

    @Override
    public Fetcher<E> fetch() {
        final TypedResultSet<E> that = this;
        return new Fetcher<>(new Builder<TypedResultSet<E>>() {
            @Override
            public TypedResultSet<E> build() {
                return that;
            }
        });
    }

    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {
            boolean next = true;
            boolean hasNexted = false;
            @Override
            public boolean hasNext() {
                if (!hasNexted) {
                    try {
                        next = resultSet.next();
                        hasNexted = true;
                    } catch (SQLException e) {
                        throw ExceptionFactory.make(e);
                    }
                }
                return next;
            }

            @Override
            public E next() {
                if (!hasNext()) {
                    throw new NoSuchElementException();
                }
                hasNexted = false;
                return getObject();
            }

            @Override
            public void remove() {
                hasNexted = false;
                try {
                    resultSet.deleteRow();
                } catch (SQLException e) {
                    throw ExceptionFactory.make(e);
                }
            }
        };
    }
}
